/* 
    // scroll-view 处理下拉刷新与触底加载
    // 王欢
    // 2020/1/15
    // ## 注意
    //     默认阈值为 45
    //     如果自定义插槽存在  则为插槽的高度
    //     默认滚动方向为 y轴
    //     插槽自定义样式可根据  sv_scroll_xy  sv_refresher_code 自定义
    // ### 需求自由配置  记得设置 scroll view 高度
    // ### m-tabs demo
    // ### 默认开启左右滑动事件
    // ### listShow 配置是否显示 u-tabs列表导航 
    // mt-tabs为依赖uview组件库tabs组件  二次封装的tabs自定义组件
    <m-tabs 
        :list="sv_tabsInfo" 
        :listShow="true"
        :current="sv_tabsIndex" 
        name="title" 
        @change="sv_tabsChange"
    >
    <!--
        scroll-view 默认适配内容区域最小高度
        可以根据布局 自定义设置 scroll-view的高度
    -->
      <scroll-view
        class=""
        :scroll-y=" sv_direction === 'y' "
        :refresher-enabled=" sv_refresher_enabled "
        :refresher-threshold=" sv_refresher_threshold "
        :refresher-default-style=" sv_refresher_default_style "
        :refresher-background=" sv_refresher_background "
        :refresher-triggered=" sv_refresher_triggered "
        @scrolltolower="sv_scrolltolower"
        @refresherpulling="sv_refresherpulling"
        @refresherrefresh="sv_refresherrefresh"
        @refresherrestore="sv_refresherrestore"
        @refresherabort="sv_refresherabort"
      >
      
        <!-- ###
            :refresher-default-style=" sv_refresher_default_style "
            自定义插槽可选   当默认插槽不存在时   在初次加载时应设置  sv_refresher_default_style 对应的style  'white' || 'black' 
            当自定义插槽不存在时   初次加载   默认还原  sv_refresher_default_style 为  white
            自定义插槽    必须设置一个固定高度  可以直接在style里面设置 或者 用class设置 
            自定义插槽  样式 结构自定义  默认样式在App.vue定义
            阈值默认等于高度 
        -->
        <template v-slot:refresher>
          <view 
            :id="sv_slot_id"
            style="height:100rpx;"
            class="m-tab__scrollView_slot"
          >{{ sv_refresher_notic }}</view>
        </template>
        
        <!-- #####
            内容区域   -->
        <block>
            <view
                class="item"
                v-for="(item,index) in sv_tabsInfo[sv_tabsIndex].list "
                :key="index"
            >item view</view>
        </block>

        <!-- 提示  
            默认 sv_tabsInfo有一个全部的配置子选项
            提示区域  当sv_tabsInfo 有正确的子选项配置情况下会显示  没有子选项的情况下隐藏
        -->
        <block >
          <view v-if="sv_tabsInfo[sv_tabsIndex].end">
            <u-empty description="当前列表没有内容哦" v-if="!sv_tabsInfo[sv_tabsIndex].list.length" />
            <u-divider v-else-if="sv_tabsEndNoticShow && sv_tabsInfo[sv_tabsIndex].count !== 1 ">
                {{ v_tabsEndNoticText }}
            </u-divider>
          </view>
          <u-loading size="24px" v-if="sv_tabsReachBottomLoading" >
            {{ sv_tabsReachBottomLoadingText }}
          </u-loading>
        </block>


      </scroll-view>
    </m-tabs>
*/

/* 2021/8/2 
    新添 scroll-view item的居中滑动
    配置
        ##必要配置
         // scroll-view 元素 class 或 id
        sv_scrollClass:""
         //  scroll-view  子元素 class
        sv_scrollItemClass:""
        可选配置
            //自定义scroll-left 存储变量
        sv_scrollLeftModel

*/
const mixin_scrollToView = require("./mixin_scrollToView");
module.exports = {
    data() {
        return {
            /* ----------------  常用配置项 start  ---------------- */

            // tabs数据列表
            sv_tabsInfo: [{
                //标题
                title: "全部"
                // query type
                , type: 0
                // 页码
                , count: 1
                // 数据是否加载完
                , end: false
                // 数据列表
                , list: []
                /* 
                // 置顶数据
                , topList: []
                // 置顶数据合并 key
                , topKey: "" 
                */
            }]
            // tabs索引
            , sv_tabsIndex: 0
            // tabs http path
            , sv_tabsHttpPath: ""
            // 列表初次加载生命周期事件 - onLoad onShow custom自定义
            , sv_tabsInitLife: "custom"
            // tabs http query转换设置
            , sv_tabsHttpKeys: {
                type: "type"
                , count: "page"
                , sv_tabsPageLimit: "limit"
            }
            // tabs一页数据量
            , sv_tabsPageLimit: 10
            // 是否使用 vant tabs
            , sv_setVantAuto: false
            // 是否开启滑动切换
            , sv_openScrollToView: false
            // 是否开启  触底加载
            , sv_openReachBottom: true
            //scroll-view 元素 class 或 id
            , sv_scrollClass: ""
            // scroll-view  子元素 class
            , sv_scrollItemClass: ""
            // scroll-view scroll-left载入的model
            , sv_scrollLeftModel: "v_scrollLeft"
            // scroll-vew data  scrollleft -- model
            , sv_scrollLeft: ""
            // 开启自定义下拉刷新
            , sv_refresher_enabled: false
            /* ---------------- 常用配置项 end  ---------------- */
            // 切换tabs是否自动刷新
            , sv_tabsRefreshAuto: true
            // tabs 是否处于触底加载事件中
            , sv_tabsReachBottomLoading: false
            // tabs 当前页码加载完毕 提示
            , sv_tabsEndNoticText: "已经到底了哦"
            // tabs 当前页码加载完毕 提示是否显示
            , sv_tabsEndNoticShow: true
            // tabs 触底加载文本提示
            , sv_tabsReachBottomLoadingText: "loading..."
            // 滑动方向
            , sv_direction: "y"
            // 设置自定义下拉刷新阈值
            , sv_refresher_threshold: 45
            // 设置自定义下拉刷新默认样式
            , sv_refresher_default_style: "none"
            // 设置自定义下拉刷新区域背景颜色
            , sv_refresher_background: "#FFF"
            //  设置当前下拉刷新状态，true 表示下拉刷新已经被触发，false 表示下拉刷新未被触发
            , sv_refresher_triggered: false
            // 开启 scroll anchoring 特性，即控制滚动位置不随内容变化而抖动
            , sv_scroll_anchoring: true
            // 当前滑动的值
            , sv_scroll_xy: 0
            // 下拉刷新插槽 id
            , sv_slot_id: "scroll_refresher"
            // 下拉刷新提示文本
            , sv_refresher_notic: ""
            // 下拉刷新 复位 未达到阈值 提示文本
            , sv_refresher_notic_restore: "下拉刷新"
            //	下拉刷新 达到阈值 提示文本
            , sv_refresher_notic_refresh: "松手即可刷新"
            // 下拉刷新 http请求中 提示文本
            , sv_refresher_notic_httpBefore: "请求中"
            // 下拉刷新 http请求成功 提示文本
            , sv_refresher_notic_httpSuc: "刷新成功"
            // 下拉刷新 http请求失败 提示文本
            , sv_refresher_notic_httpFail: "刷新失败"
            // 下拉刷新  http请求完成 复位间隔时间
            , sv_refresher_restore_timeSplit: 500
            // 滑动状态码
            /* 
                0 复位
                1 未达到阈值
                2 达到阈值
                3 http请求中
                4 http请求成功
                5 http请求失败
            */
            , sv_refresher_code: 0
        }
    }
    , mixins: [mixin_scrollToView]
    /* 
        ,computed:{
            // ## tabs http query 合并的参数
            sv_tabsHttpQueryAssignInfo(){
                return {};
            }
        } 
    */

    /* ----------------  必须配置项 end  ---------------- */
    , onLoad() {
        this.sv_getTabsInitLife("onLoad");
    }
    , onShow() {
        this.sv_getTabsInitLife("onShow");
    }
    , onReady() {
        // 如果自定义插槽存在   获取插槽高度为阈值
        const page = this;
        const { sv_refresher_enabled, sv_slot_id } = page;
        if (sv_refresher_enabled) {
            if (sv_slot_id) {
                uni.createSelectorQuery()
                    .select('#' + sv_slot_id)
                    .boundingClientRect(res => {
                        if (res) {
                            page.sv_refresher_threshold = res.height;
                        } else {
                            page.sv_refresher_default_style = "white";
                            page.sv_refresher_enabled = false;
                        }

                    }).exec();
            } else {
                page.$fail("scrollTabs Error: missing params sv_slot_id")
            }
        }
    }
    , methods: {
        /* ----------------  必须配置项 start  ---------------- */
        /* 
            自定义处理当前列表参数  每个项目可根据接口单独设置
            list  列表
            end   列表是否加载结束
            传入的值 
                res 接口返回值
                tabsItem    sv_tabsInfo[sv_tabsIndex] 当前索引对象
                concatAuto  是否拼接  true 拼接 false 赋值
            返回一个新的 当前索引对象
            
        */
        sv_updateTabsItem({
            res
            , tabsItem
            , concatAuto
        }) {
            const page = this;
            //前后台定义 一页数据量
            const { data } = res;
            const { sv_tabsPageLimit } = page;
            tabsItem.end = data.length < sv_tabsPageLimit;
            /* 
                //通过接口返回  总页数
                const { data: { total, list:data } } = res;
                const { pageCount } = tabsItem;
                tabsItem.end = total == 0 || pageCount == total;;
            
            */
            if (concatAuto) {
                tabsItem.list = tabsItem.list.concat(data);
            } else {
                tabsItem.list = data;
            }
            return tabsItem;
        }
        /* ----------------  必须配置项 end  ---------------- */

        /* 
            // 对 tabsInfo data 进行处理
            ,sv_tabsDataTransform( tabsData ){} 
        */
        // scroll view 触底或者触右加载
        , sv_scrolltolower() {
            const page = this;
            page.sv_tabsReachBottom();
        }
        // scroll view 自定义下拉刷新控件被下拉	
        , sv_refresherpulling(event) {
            const page = this;
            let { sv_refresher_threshold
                , sv_refresher_notic_refresh
                , sv_refresher_notic_restore
            } = page;
            const { deltaY } = event.detail;
            let code;
            let notic;
            if (deltaY < sv_refresher_threshold) {
                code = 1;
                notic = sv_refresher_notic_restore;
            } else {
                code = 2;
                notic = sv_refresher_notic_refresh;

            }
            page.sv_refresher_code = code;
            page.sv_scroll_xy = deltaY;
            page.sv_refresher_notic = notic;

        }
        // scroll view 自定义下拉刷新被触发	
        , sv_refresherrefresh() {
            // console.log("下拉刷新");
            const page = this;
            let { sv_refresher_notic_httpBefore
                , sv_refresher_notic_httpSuc
                , sv_refresher_notic_httpFail
                , sv_refresher_restore_timeSplit
            } = page;
            page.sv_refresher_notic = sv_refresher_notic_httpBefore;
            page.sv_refresher_code = 3
            page.sv_refresher_triggered = true;
            function callbackCpt({ notic, code, err }) {
                page.sv_refresher_code = code;
                page.sv_refresher_notic = notic;
                setTimeout(function () {
                    page.sv_refresher_notic = notic;
                    page.sv_refresher_triggered = false;
                }, sv_refresher_restore_timeSplit);
                if (err) {
                    page.$fail(err);
                }
            }
            page.sv_tabsPullDownRefresh({
                success() {
                    callbackCpt({
                        notic: sv_refresher_notic_httpSuc
                        , code: 4
                    });
                }
                , fail(err) {
                    callbackCpt({
                        notic: sv_refresher_notic_httpFail
                        , code: 5
                        , err
                    });
                }
            })
        }
        // scroll view 自定义下拉刷新被中止	
        , sv_refresherabort(event) {
            this.sv_refresherrestore();
        }
        // scroll view 自定义下拉刷新被复位	
        , sv_refresherrestore() {
            // console.log("下拉复位");
            const page = this;
            let { sv_refresher_notic_restore } = page;
            page.sv_refresher_code = 0
            page.sv_scroll_xy = 0
            page.sv_refresher_notic = sv_refresher_notic_restore
            page.sv_refresher_triggered = false;
        }
        // 置顶数据筛选
        , sv_topMerge(navItem) {
            // 置顶数据拼接
            const { topList, topKey, list } = navItem;
            if (topList && topList.length) {
                if (topKey && list.length) {
                    const { list } = navItem;

                    for (let i = list.length - 1; i >= 0; i--) {
                        let listItem = list[i];
                        let hasTop = topList.some(item => {
                            return item[topKey] == listItem[topKey];
                        })

                        if (hasTop) {
                            list.splice(i, 1);
                        }
                    }
                }

                navItem.list.unshift(...topList);
            }
            return navItem;
        }
        // 初次加载
        , sv_getTabsInitLife(lifeName) {
            const page = this;
            const { sv_tabsRefreshAuto, sv_tabsIndex, sv_tabsInitLife } = page;
            if (sv_tabsInitLife && sv_tabsInitLife === lifeName) {
                page.sv_tabsChange(undefined, {
                    tabs_index: sv_tabsIndex
                    , refresh_auto: sv_tabsRefreshAuto

                });
            }
        }
        //加载分页内容
        , sv_getTabsPage(params) {
            const page = this;
            const { sv_tabsHttpKeys
                , sv_tabsHttpQueryAssignInfo
                , sv_tabsHttpPath
            } = page;
            const httpQuerys = {};
            Object.keys(sv_tabsHttpKeys)
                .forEach(key => {
                    const transKey = sv_tabsHttpKeys[key];
                    if (transKey) {
                        httpQuerys[transKey] = params[key];
                    }
                });
            if (sv_tabsHttpQueryAssignInfo) {
                Object.assign(httpQuerys, sv_tabsHttpQueryAssignInfo);
            }
            // 搜索关键字
            const { searchKeys } = params;
            if (searchKeys) {
                Object.assign(httpQuerys, searchKeys);
            }
            return page.$get(sv_tabsHttpPath, httpQuerys);
        }
        , sv_tabsChange(event, navInfo) {
            const page = this;
            let { sv_tabsInfo, sv_tabsPageLimit, sv_tabsRefreshAuto, sv_tabsIndex, sv_setVantAuto } = page;
            if (!sv_tabsInfo.length) {
                throw Error("scrollTabs Error: tabsInfo length is null");
            }
            let refreshAuto = sv_tabsRefreshAuto;
            let success;
            let fail;
            // 搜索关键字  Object 类型 
            let searchKeys;
            if (event) {
                /* 判断是否为event 组件方法监听 还是自定义监听 */
                const eventType = typeof event;
                /* 如果是使用组件方法 目前 u-tabs van-tabs 皆只有索引 */
                if( eventType === Number || eventType === String ){
                    sv_tabsIndex = event || 0;
                }else{
                    sv_tabsIndex = event.currentTarget.dataset.tabs_index;
                    const eventDataset = event.currentTarget.dataset;
                    searchKeys = eventDataset.search_keys;
                    if ("refresh_auto" in eventDataset) {
                        refreshAuto = eventDataset.refresh_auto;
                    }
                }
            } else if (navInfo) {
                sv_tabsIndex = navInfo.tabs_index;
                searchKeys = navInfo.search_keys;
                callback = navInfo.callback;
                success = navInfo.success;
                fail = navInfo.fail;
                if ("refresh_auto" in navInfo) {
                    refreshAuto = navInfo.refresh_auto;
                }
            } else {
                throw ReferenceError("scrollTabs Error: tabsChange missing required parameter")
            }
            page.sv_tabsIndex = sv_tabsIndex;
            /* 是否滑动切换 */
            const { sv_openScrollToView } = page;
            // 前提不使用 vant组件
            if (!sv_setVantAuto && sv_openScrollToView) {
                const { sv_scrollClass, sv_scrollItemClass, sv_scrollLeftModel } = page;
                page.scrollIntoView({
                    scrollClass: sv_scrollClass
                    , scrollItemClass: sv_scrollItemClass
                    , scrollIndex: sv_tabsIndex
                    , scrollLeftModel: sv_scrollLeftModel
                });
            }

            let navItem = sv_tabsInfo[sv_tabsIndex];

            // 切换加载  条件
            // 强制刷新开启
            //  或者   没有加载完  并且  数据为0
            if (refreshAuto || (
                !navItem.end
                &&
                !navItem.list.length
            )) {
                if (refreshAuto) {
                    navItem.pageCount = 1;
                }
                const { type, pageCount } = navItem;
                page.sv_getTabsPage({
                    type
                    , pageCount
                    , sv_tabsPageLimit
                    , searchKeys
                })
                    .then(res => {
                        const { sv_tabsDataTransform } = page;
                        // 处理当前列表 数据
                        if (sv_tabsDataTransform && typeof sv_tabsDataTransform === "function") {
                            list = sv_tabsDataTransform(list);
                        }
                        // 处理当前列表数据  是否结束   列表数据赋值
                        navItem = page.sv_updateTabsItem({ tabsItem: navItem, res, concatAuto: false });
                        // 处理当前列表  置顶数据   
                        navItem = page.sv_topMerge(navItem);
                        if (success && typeof success === "function") {
                            success();
                        }

                    }).catch(err => {
                        if (fail && typeof fail === "function") {
                            fail(err);
                        } else {
                            page.$fail(err);
                        }
                    });
            }



        }
        // tabs 下拉刷新
        , sv_tabsPullDownRefresh({ success, fail }) {
            const page = this;
            const { sv_tabsIndex } = page;
            page.sv_tabsChange(undefined, {
                tabs_index: sv_tabsIndex
                , refresh_auto: true
                , success
                , fail
            });
        }
        // tabs 触底加载
        , sv_tabsReachBottom() {
            const page = this;
            let { sv_tabsInfo, sv_tabsIndex, sv_tabsPageLimit, sv_tabsReachBottomLoading } = page;
            let navItem = sv_tabsInfo[sv_tabsIndex];
            const { pageCount, end, type } = navItem;
            // 如果处于触底加载事件中  退出
            if (sv_tabsReachBottomLoading) {
                return false;
            }
            if (end) {
                return false;
            } else {
                page.sv_tabsReachBottomLoading = true;
                const nextpageCount = pageCount + 1;
                page.sv_getTabsPage({
                    type
                    , pageCount: nextpageCount
                    , sv_tabsPageLimit
                }).then(res => {
                    // 处理当前列表数据  是否结束   列表数据赋值
                    navItem = page.sv_updateTabsItem({ tabsItem: navItem, res, concatAuto: true });
                    navItem.pageCount = nextpageCount;
                    page.sv_tabsReachBottomLoading = false;
                    // navItem = page.sv_topMerge( navItem );
                }).catch(err => {
                    page.sv_tabsReachBottomLoading = false;
                    page.$fail(err);
                });
            }
        }
    },

}